<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>画直线</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
        <!-- <script src="../../build/three.module.js"></script> -->
        <!-- <script src="../../examples/jsm/libs/stats.module.js"></script> -->
        <!-- <script src="../../examples/jsm/controls/OrbitControls.js"></script> -->
</head>
<body>
<script type="importmap">
    {
        "imports": {
          "three": "./test/build/three.module.js",
          "three/addons/": "./test/jsm/"
        }
      }
</script>
<script type="module">
    import * as THREE from 'three';
    import Stats from 'three/addons/libs/stats.module.js';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    var scene, camera, renderer, controls;
    var stats = initStats();

    /* 地面网格所需变量 */
    var length = 200;  /*线段长度*/

    /* 场景 */
    function initScene() {

        scene = new THREE.Scene();
        // 创建辅助观察坐标系
        const asesHelper = new THREE.AxesHelper(100);
        scene.add(asesHelper);
    }

    /* 相机 */
    function initCamera() {

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
        camera.position.set(0, 200, 250);
        // camera.up.x = 0;
        // camera.up.y = 0;
        // camera.up.z = 1;  
        camera.lookAt(new THREE.Vector3(0, 0, 0));

    }

    /* 渲染器 */
    function initRender() {

        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

    }

    /* 灯光 */
    function initLight() {

        var ambientLight = new THREE.AmbientLight(0x333333);
        scene.add(ambientLight);

        var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(100, 300, 200);
        scene.add(directionalLight);

    }

    /* 控制器 */
    function initControls() {

        controls = new OrbitControls(camera, renderer.domElement);
        /* 其它属性默认 */

    }

    /* 场景内容 */
    function initContent() {

        var geometry = new THREE.BufferGeometry();/* 简单基础几何 */
        var lineMaterial = new THREE.LineBasicMaterial({color: 0x808080});/* 基础线材质 */

        var planeGeometry = new THREE.PlaneGeometry(length, 10);/* 平面 width：200,、height：10 */
        var planeMaterial = new THREE.MeshBasicMaterial({color: 0xD9D9D9, side: THREE.DoubleSide});/* 平面材质 */

        // geometry.vertices.push(new THREE.Vector3(-length / 2, 0, 0));/* 顶点(-100, 0, 0) */
        // geometry.vertices.push(new THREE.Vector3(length / 2, 0, 0)); /* 顶点( 100, 0, 0) */
        const pointsArray2 = new Array()
        // for (let i = 0; i < 2000; i++) {
        //     const x = Math.random() * 2 - 1;
        //     const y = Math.random() * 2 - 1;
        //     const z = Math.random() * 2 - 1;
        //     pointsArray.push(new THREE.Vector3(x,y,z))
        // }
        pointsArray2.push(new THREE.Vector3(-length / 2, 0, 0))
        pointsArray2.push(new THREE.Vector3(length / 2, 0, 0))
        geometry.setFromPoints(pointsArray2)
        /* 循环创建线段 */
        for (var i = 0; i <= length / 10; i++){

            /* 横向线段 */
            var lineX = new THREE.Line(geometry, lineMaterial);
            lineX.position.z = (i * 10) - length / 2;
            scene.add(lineX);

            /* 纵向线段 */
            var lineY = new THREE.Line(geometry, lineMaterial);
            lineY.rotation.y = 0.5 * Math.PI;
            lineY.position.x = (i * 10) - length / 2;
            scene.add(lineY);

        }

        /* 创建包围平面 */
        var planeX_left = new THREE.Mesh(planeGeometry, planeMaterial);
        planeX_left.rotation.y = 0.5 * Math.PI;
        planeX_left.position.x = -length / 2;

        var planeX_right = planeX_left.clone();
        planeX_right.position.x = length / 2;

        var planeY_top = new THREE.Mesh(planeGeometry, planeMaterial);
        planeY_top.position.z = -length / 2;

        var planeY_bottom = planeY_top.clone();
        planeY_bottom.position.z = length / 2;

        scene.add(planeY_bottom);
        scene.add(planeY_top);
        scene.add(planeX_left);
        scene.add(planeX_right);

        /* 四个包围面的位置 y轴向上5 */
        scene.traverse(function (object) {

            if (object.isMesh){

                if (object.geometry.type === 'PlaneGeometry'){

                    object.position.y = 5;

                }

            }

        });

    }

    /* 获取射线与平面相交的交点 */
    function getIntersects(event) {

        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();

        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        var normal = new THREE.Vector3(0, 1, 0);
        /* 创建平面 */
        var planeGround = new THREE.Plane(normal, 0);

        /* 从相机发出一条射线经过鼠标点击的位置 */
        raycaster.setFromCamera(mouse, camera);

        /* 获取射线 */
        var ray = raycaster.ray;
        // console.log('123')
        // console.log('123', ray, planeGround)
        /* 计算相机到射线的对象，可能有多个对象，返回一个数组，按照距离相机远近排列 */
        var intersects = ray.intersectPlane(planeGround, planeGround.normal);

        /* 返回向量 */
        return intersects;

    }

    var pointsArray = [];
    var pointsSaveArray = [];
    var window_mouse = true;
    /* 鼠标按下事件 */
    function onMouseDown(event) {

        /* 获取相机发出的射线与 Plane 相交点*/
        var intersects = getIntersects(event);

        /* 存放网格的三维坐标 */
        var vector3_x, vector3_z;

        /* 鼠标左键按下时，创建点和线段 */
        if (event.button === 0) {

            if (!window_mouse){

                window.addEventListener('mousemove', onMouseMove, false);

                /* 依据 windwo_mouse 标识避免事件的重复添加 */
                window_mouse = true;

            }

            /* 判断交点是否在 x(-100, 100) ，z(-100, 100)(平面)之间 */
            if (Math.abs(intersects.x) < length / 2 && Math.abs(intersects.z) < length / 2){

                /* 若交点此时在平面之内则创建点（Points） */
                var pointsGeometry = new THREE.BufferGeometry();

                // pointsGeometry.vertices.push(intersects.x,intersects.y,);
                const pointsArray3 = new Array()
                pointsArray3.push(intersects)
                // pointsArray3.push(intersects.z)
                pointsGeometry.setFromPoints(pointsArray3)

                var pointsMaterial = new THREE.PointsMaterial({color:0xff0000, size: 3});
                // console.log('456-1', pointsGeometry)
                // console.log('456-2', intersects)
                var points = new THREE.Points(pointsGeometry, pointsMaterial);

                pointsArray.push(points);
                pointsSaveArray.push(points);

                /* 创建线段 */
                var lineGeometry = new THREE.BufferGeometry();
                var lineMaterial = new THREE.LineBasicMaterial({color: 0x00ff00});

                if (pointsArray.length >= 2) {

                    // lineGeometry.vertices.push(pointsArray[0].geometry.vertices[0], pointsArray[1].geometry.vertices[0]);
                    const pointsArray4 = new Array()
                    const abc = pointsArray[0].geometry.attributes.position
                    const efg = pointsArray[1].geometry.attributes.position
                    for (let index = 0; index < abc.count; index++) {
                        const x = abc.getX(index)
                        const y = abc.getY(index)
                        const z = abc.getZ(index)
                        pointsArray4.push(new THREE.Vector3(x, y, z))
                    }
                    for (let index = 0; index < efg.count; index++) {
                        const x = efg.getX(index)
                        const y = efg.getY(index)
                        const z = efg.getZ(index)
                        pointsArray4.push(new THREE.Vector3(x, y, z))
                    }
                    lineGeometry.setFromPoints(pointsArray4)

                    var line = new THREE.Line(lineGeometry, lineMaterial);
                    pointsArray.shift();
                    scene.add(line);

                }

                scene.add(points);

            }

        }

        /* 鼠标右键按下时 回退到上一步的点，并中断绘制 */
        if (event.button === 2) {

            window.removeEventListener('mousemove', onMouseMove, false);

            /* 移除事件之后，要设置为 false 为了避免事件的重复添加 */
            window_mouse = false;

            /* 鼠标左键未点击时线段的移动状态 */
            if (scene.getObjectByName('line_move')) {

                scene.remove(scene.getObjectByName('line_move'));

                /* 删除数组中的元素，否则的话再次重绘会链接之前的点接着重绘 */
                pointsArray.shift();

            }
            if (pointsSaveArray.length >= 2) {
                var lineGeometry = new THREE.BufferGeometry();
                var lineMaterial = new THREE.LineBasicMaterial({color: 0x00ff00});
                const pointsArray4 = new Array()
                const abc = pointsSaveArray[0].geometry.attributes.position
                const efg = pointsSaveArray[pointsSaveArray.length - 1].geometry.attributes.position
                // console.log('555', pointsSaveArray[length - 1])
                for (let index = 0; index < abc.count; index++) {
                    const x = abc.getX(index)
                    const y = abc.getY(index)
                    const z = abc.getZ(index)
                    pointsArray4.push(new THREE.Vector3(x, y, z))
                }
                for (let index = 0; index < efg.count; index++) {
                    const x = efg.getX(index)
                    const y = efg.getY(index)
                    const z = efg.getZ(index)
                    pointsArray4.push(new THREE.Vector3(x, y, z))
                }
                lineGeometry.setFromPoints(pointsArray4)

                var line = new THREE.Line(lineGeometry, lineMaterial);
                // pointsSaveArray = [];
                scene.add(line);
                
                console.log('pointsSaveArray', pointsSaveArray)
                //类型化数组创建顶点数据
                getpointsArray(pointsSaveArray)
            }

        }

    }

    /* 鼠标移动事件 */
    function onMouseMove(event) {

        var intersects = getIntersects(event);

        /* 判断交点是否在 x(-100, 100) ，z(-100, 100)(平面)之间 */
        if (intersects && (Math.abs(intersects.x) < length / 2 && Math.abs(intersects.z) < length / 2)) {

            /* 鼠标左键未点击时线段的移动状态 */
            if (scene.getObjectByName('line_move')) {

                scene.remove(scene.getObjectByName('line_move'));

            }
            /* 创建线段 */
            var lineGeometry = new THREE.BufferGeometry();
            var lineMaterial = new THREE.LineBasicMaterial({color: 0x00ff00});

            if (pointsArray.length > 0){

                // lineGeometry.vertices.push(pointsArray[0].geometry.vertices[0]);
                const pointsArray5 = new Array()
                // console.log('321-3', pointsArray[0].geometry.attributes.position.array)
                const abc = pointsArray[0].geometry.attributes.position
                for (let index = 0; index < abc.count; index++) {
                    const x = abc.getX(index)
                    const y = abc.getY(index)
                    const z = abc.getZ(index)
                    // console.log('321-4', x, y, z)
                    // lineGeometry.setFromPoints(new THREE.Vector3(x, y, z))
                    pointsArray5.push(new THREE.Vector3(x, y, z))
                    // pointsArray5.push(new THREE.Vector3(0))
                    // pointsArray5.push(new THREE.Vector3(z))
                }
                // pointsArray5.push(pointsArray[0])
                // lineGeometry.setFromPoints(pointsArray5)

                var mouseVector3 = new THREE.Vector3(intersects.x, 0, intersects.z);

                // lineGeometry.vertices.push(mouseVector3);
                
                pointsArray5.push(mouseVector3)
                lineGeometry.setFromPoints(pointsArray5)
                // console.log('321-5', lineGeometry)
                var line = new THREE.Line(lineGeometry, lineMaterial);
                line.name = 'line_move';

                scene.add(line);

            }

        }

    }

    /* 键盘按下事件 */
    function onKeyDown(event) {

        /* ESC键 回退上一步绘制，结束绘制*/
        if (event.key === 'Escape'){

            window.removeEventListener('mousemove', onMouseMove, false);

            /* 移除事件之后，要设置为 false 为了避免 mousemove 事件的重复添加 */
            window_mouse = false;

            /* 鼠标左键未点击时线段的移动状态 */
            if (scene.getObjectByName('line_move')) {

                scene.remove(scene.getObjectByName('line_move'));

                /* 删除数组中的元素，否则的话再次重绘会链接之前的点接着重绘 */
                pointsArray.shift();

            }

            var length = scene.children.length - 1;
            /* 按步骤移除点和先 */
            if (scene.children[length].isLine || scene.children[length].isPoints){

                scene.children.pop();
                length = scene.children.length - 1;

                /* 若最后一项不是线段或者点就不移除 */
                if (!scene.children[length].isMesh) {

                    scene.children.pop();

                }

            }

        }

    }
    function getpointsArray(params) {
        const pointsArray4 = new Array()
        params.forEach((e, index) => {
            if (index !== 0 && index > 2) {
                const x = params[0].geometry.attributes.position.getX(0)
                const y = params[0].geometry.attributes.position.getY(0)
                const z = params[0].geometry.attributes.position.getZ(0)
                pointsArray4.push(x)
                pointsArray4.push(y)
                pointsArray4.push(z)
                console.log('index执行整除', params.length, index)
                const x2 = params[index - 1].geometry.attributes.position.getX(0)
                const y2 = params[index - 1].geometry.attributes.position.getY(0)
                const z2 = params[index - 1].geometry.attributes.position.getZ(0)
                pointsArray4.push(x2)
                pointsArray4.push(y2)
                pointsArray4.push(z2)
                console.log('x', x, 'x2', x2)
            }
            for (let i = 0; i < e.geometry.attributes.position.count; i++) {
                const x = e.geometry.attributes.position.getX(i)
                const y = e.geometry.attributes.position.getY(i)
                const z = e.geometry.attributes.position.getZ(i)
                pointsArray4.push(x)
                pointsArray4.push(y)
                pointsArray4.push(z)
                console.log('index正常添加', index)
            }
        })
        console.log('pointsArray4pointsArray4', pointsArray4)
        const geometry = new THREE.BufferGeometry();
        const vertices = new Float32Array(pointsArray4);
        
        // 创建属性缓冲区对象
        //3个为一组，表示一个顶点的xyz坐标
        const attribue = new THREE.BufferAttribute(vertices, 3);
        // 设置几何体attributes属性的位置属性
        geometry.attributes.position = attribue;
        // // 点渲染模式
        // const material = new THREE.PointsMaterial({
        //   color: 0xffff00,
        //   size: 20.0 //点对象像素尺寸
        // });
        // const points = new THREE.Points(geometry, material); //点模型对象
        
        // // 线材质对象
        // const material = new THREE.LineBasicMaterial({
        //   color: 0xffff00 //线条颜色
        // });
        // // 创建线模型对象
        // const line = new THREE.LineSegments(geometry, material);
        
        // 正面：逆时针
        // 反面：顺时针
        const material = new THREE.MeshBasicMaterial({
        color: 0x0000ff, //材质颜色
        // side: THREE.FrontSide, //默认只有正面可见
        side: THREE.DoubleSide, //两面可见
        // side: THREE.BackSide, //设置只有背面可见
        });
        
        const mesh = new THREE.Mesh(geometry, material)
        scene.add(mesh);
        pointsSaveArray = [];
    }

    /* 更新数据 */
    function update() {

        stats.update();
        // controls.update();

    }

    /* 性能插件 */
    function initStats() {

        var stats = new Stats();

        stats.setMode(0);
        stats.domElement.style.position = 'absolute';
        stats.domElement.style.left = '0px';
        stats.domElement.style.right = '0px';

        document.body.appendChild(stats.domElement);

        return stats;

    }

    /* 窗口自动适应 */
    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);

    }

    /* 循环调用 */
    function animate() {

        requestAnimationFrame(animate);
        renderer.render(scene, camera);
        update();

    }

    /* 初始化 */
    function init() {

        /* 兼容性判断 */
        //if (!Detector.webgl) Detector.addGetWebGLMessage();

        initScene();
        initCamera();
        initRender();
        // initLight();
        initContent();
        initControls();

        /* 事件监听 */
        window.addEventListener('resize', onWindowResize, false);
        window.addEventListener('mousedown', onMouseDown, false);/* 使用mousedown的时候可以判断出点击的鼠标左右键之分 */
        window.addEventListener('mousemove', onMouseMove, false);
        window.addEventListener('keydown', onKeyDown, false);/* 使用事件的时候要把前面的on给去掉 */

    }

    /* 初始加载 */
    (function () {

        console.log('three start...');

        init();
        animate();

        console.log('three end...');

    })();

</script>
</body>
</html>